package org.mysterylab.utopiaframework.web.util.json;

import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;

import org.apache.commons.lang.StringUtils;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.DeserializationConfig.Feature;
import org.codehaus.jackson.map.annotate.JsonSerialize.Inclusion;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 对 Jackson 的第二次封装, 提供了一些实用的 JSON 方法.
 * 
 * @author zhouych
 */
public class JsonUtil {

	private static Logger logger = LoggerFactory.getLogger(JsonUtil.class);
	
	private ObjectMapper objectMapper;
	
	public JsonUtil(Inclusion inclusion) {
		objectMapper = new ObjectMapper();
		// 设置输出包含的属性
		objectMapper.getSerializationConfig().setSerializationInclusion(inclusion);
		// 设置输入时忽略 JSON 字符串中存在而 Java 对象实际没有的属性
		objectMapper.getDeserializationConfig().set(
				Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
	}
	
	/**
	 * 创建输出全部属性到 JSON 字符串的 Inclusion.
	 * 
	 * @return
	 */
	public static JsonUtil buildNormalInclusion() {
		return new JsonUtil(Inclusion.ALWAYS);
	}
	
	/**
	 * 创建只输出初始值被改变的属性到 JSON 字符串的 Inclusion.
	 * 
	 * @return
	 */
	public static JsonUtil buildNonDefaultInclusion() {
		return new JsonUtil(Inclusion.NON_DEFAULT);
	}
	
	/**
	 * 创建只输出非空属性到 JSON 字符串的 Inclusion.
	 */
	public static JsonUtil buildNonNullInclusion() {
		return new JsonUtil(Inclusion.NON_NULL);
	}
	
	/**
	 * 从 JSON 字符串生成相应的 Java 对象.<br>
	 * <ul>
	 * 	<li>如果 JSON 字符串为 NULL 或 "null", 则返回 null.</li>
	 * 	<li>如果 JSON 字符串为 "[]", 则返回空集合.</li>
	 * </ul>
	 * 
	 * @param <T>
	 * @param jsonString
	 * @param clazz
	 * @return
	 */
	public <T> T fromJson(String jsonString, Class<T> clazz) {
		if (StringUtils.isEmpty(jsonString)) {
			return null;
		}
		try {
			return objectMapper.readValue(jsonString, clazz);
		} catch (IOException e) {
			logger.warn("parse json string error: " + jsonString, e);
			return null;
		}
	}
	
	/**
	 * 将 Java 对象生成 JSON 格式.<br>
	 * <ul>
	 * 	<li>如果对象为 null, 则返回 "null".</li>
	 * 	<li>如果对象为空集合, 则返回 "[]".</li>
	 * </ul>
	 * 
	 * @param object
	 * @return
	 */
	public String toJson(Object object) {
		try {
			return objectMapper.writeValueAsString(object);
		} catch (IOException e) {
			logger.warn("write a json string error: " + object, e);
			return null;
		}
	}
	
	/**
	 * 设置转换日期类型的 format pattern.
	 * 
	 * @param pattern
	 */
	public void setDateFormat(String pattern) {
		if (StringUtils.isNotBlank(pattern)) {
			DateFormat df = new SimpleDateFormat(pattern);
			objectMapper.getSerializationConfig().setDateFormat(df);
			objectMapper.getDeserializationConfig().setDateFormat(df);
		}
	}

	public ObjectMapper getObjectMapper() {
		return objectMapper;
	}
}
